# coding=utf-8
from flask import g, url_for
from oss2 import Auth, Bucket
from oss2.models import RequestResult

from apps.a_common.log import MyLogger
from apps.foundation import cache
from config import ALIYUN_OSS_ACCESS_KEY_ID, ALIYUN_OSS_ACCESS_KEY_SECRET, ALI_OSS_EP, HOST, BUCKET_NAME, \
    IMAGE_RESIZE_HEIGHT
from utils.time import timer


logger = MyLogger('oss util')
STRING_FORAMT = 'txt/{}'
IMAGE_FORMAT = 'image/{}'

"""####################################### BASE & COMMON #######################################"""


def create_oss_bucket():
    auth = Auth(ALIYUN_OSS_ACCESS_KEY_ID, ALIYUN_OSS_ACCESS_KEY_SECRET)
    bucket = Bucket(auth, ALI_OSS_EP, BUCKET_NAME)
    return bucket


def get_or_create_oss_bucket_to_g() -> Bucket:
    if not hasattr(g, 'oss_bucket'):
        g.oss_bucket = create_oss_bucket()
    return g.oss_bucket


def print_log(result: RequestResult, action: str = None):
    if action:
        logger.info(f'{action} by aliOSS, status: {result.status}, request_id: {result.request_id}')
    else:
        logger.info(f'request to aliOSS, status: {result.status}, request_id: {result.request_id}')


"""####################################### INTERFACE WITH OSS #######################################"""


@timer
def post_str_to_storage(name, data):
    bucket = get_or_create_oss_bucket_to_g()
    name = STRING_FORAMT.format(name)
    result = bucket.put_object(name, data)
    print_log(result, 'upload str to oss')
    return name


@cache.memoize(timeout=3600)
@timer
def get_str_from_storage(name):
    bucket = get_or_create_oss_bucket_to_g()
    result = bucket.get_object(name)
    print_log(result, 'download str from oss')
    return result.read().decode('UTF-8')


@timer
def post_file_to_storage(name, data):
    bucket = get_or_create_oss_bucket_to_g()
    name = IMAGE_FORMAT.format(name)
    result = bucket.put_object(name, data)
    print_log(result, 'upload str(key: {}) to oss'.format(name))
    return name


@timer
def get_file_from_storage(name, size=IMAGE_RESIZE_HEIGHT):
    bucket = get_or_create_oss_bucket_to_g()
    process = f"image/resize,m_lfit,h_{size}"  # 对于图片进行强制缩
    result = bucket.get_object(name, process=process)
    print_log(result, 'get str from oss')
    return result.read()


@timer
def rename_file(old_name, new_name):
    bucket = get_or_create_oss_bucket_to_g()
    bucket.copy_object(bucket.bucket_name, source_key=old_name, target_key=new_name)
    # bucket.delete_object(old_name)


def get_file_download_url(name: str):
    return HOST + url_for('files._get_image', image_url=name)


def get_key_from_url(url: str):
    prefix = HOST + url_for('files._get_image', image_url='')[: -1]  # 两个 -1 都是为了去掉末尾的 /
    key = url.replace(prefix, '')
    if key.endswith('/'):
        key = key[:-1]
    return key
